﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects;
using System.Data;
using System.Data.Objects.DataClasses;
using System.Reflection;
using System.Runtime.Serialization;
using System.IO;
using Smartec.Framework.Common;
using Smartec.Framework.Common.CachingManager;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;

namespace Smartec.Accounts.Camel.AMS.Model.Entities
{
    public partial class AMSObjectContext
    {
        //public string UserName { get; set; }
        List<DBAudit> auditTrailList = new List<DBAudit>();

        public enum AuditActions
        {
            I,
            U,
            D
        }

        //public override int SaveChanges(SaveOptions options)
        //{
        //    DBAudit dbAudit = new DBAudit();
        //    List<DBEntity> dbEntities = this.DBEntities.ToList();

        //    List<KeyValuePair<DBAuditDetail, ObjectStateEntry>> auditDetails = new List<KeyValuePair<DBAuditDetail, ObjectStateEntry>>();
        //    try
        //    {
        //    IEnumerable<ObjectStateEntry> changes = this.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified);

        //    dbAudit.AuditId = Guid.NewGuid();
        //    dbAudit.UserName = ObjectCachingManager.CurrentUserName;
        //    dbAudit.RevisionStamp = DateTime.Now;

        //    foreach (ObjectStateEntry stateEntryEntity in changes)
        //    {
        //        if (stateEntryEntity.Entity != null && (stateEntryEntity.Entity.GetType().Equals(typeof(DBAudit)) || stateEntryEntity.Entity.GetType().Equals(typeof(DBAuditDetail))))
        //        {
        //            continue;
        //        }

        //        if (dbEntities.Any(o => o.IsMaster && o.Name == stateEntryEntity.EntitySet.Name))
        //        {
        //            dbAudit.TableName = stateEntryEntity.EntitySet.Name;
        //            if (stateEntryEntity.State != EntityState.Added)
        //            {
        //                dbAudit.MasterId = (int)((PropertyInfo)stateEntryEntity.Entity.GetType().GetProperty("ID")).GetValue(stateEntryEntity.Entity, null);
        //            }
        //            break;
        //        }
        //    }

        //    foreach (ObjectStateEntry stateEntryEntity in changes)
        //    {
        //        if (stateEntryEntity.Entity != null && (stateEntryEntity.Entity.GetType().Equals(typeof(DBAudit)) || stateEntryEntity.Entity.GetType().Equals(typeof(DBAuditDetail))))
        //        {
        //            continue;
        //        }

        //        DBAuditDetail auditDetail = this.AuditTrailFactory(stateEntryEntity);
        //        if (auditDetail != null)
        //        {
        //            auditDetails.Add(new KeyValuePair<DBAuditDetail, ObjectStateEntry>(auditDetail, stateEntryEntity));
        //        }

        //    }
        //    }
        //    catch
        //    { }

        //    int result = base.SaveChanges(options);

        //    try
        //    {
        //    if (auditDetails.Count > 0)
        //    {
        //        foreach (var audit in auditDetails)
        //        {//add all audits 
        //            if (!audit.Key.IsRelation && audit.Key.Action == AuditActions.I.ToString())//&& !audit.Value.IsRelationship
        //            {
        //                audit.Key.EntityId = (int?)audit.Value.EntityKey.EntityKeyValues[0].Value;

        //                List<string> modifiedProperties;
        //                audit.Key.NewData = GetEntryValueInString(audit.Value, false, out modifiedProperties);
        //            }

        //            if (dbAudit.MasterId == null)
        //            {
        //                if (audit.Key.TableName == dbAudit.TableName)
        //                {
        //                    dbAudit.MasterId = audit.Key.EntityId;
        //                }
        //            }
        //            dbAudit.DBAuditDetails.Add(audit.Key);

        //        }
        //        if (dbAudit.TableName !=null)
        //        {
        //            this.AddToDBAudits(dbAudit);
        //        }

        //        result = base.SaveChanges(options);
        //    }
        //    }
        //    catch
        //    { }

        //    return result;
        //}

        //private DBAuditDetail AuditTrailFactory(ObjectStateEntry entry)
        //{
        //    DBAuditDetail audit = new DBAuditDetail();
        //    audit.TableName = entry.EntitySet.Name;

        //    List<string> modifiedProperties = new List<string>();

        //    if (entry.State == EntityState.Added)
        //    {//entry is Added 
        //        //audit.NewData = GetEntryValueInString(entry, false, out modifiedProperties);
        //        audit.Action = AuditActions.I.ToString();
        //    }
        //    else if (entry.State == EntityState.Deleted)
        //    {//entry in deleted
        //        audit.OldData = GetEntryValueInString(entry, true, out modifiedProperties);
        //        audit.Action = AuditActions.D.ToString();
        //        if (!entry.IsRelationship)
        //            audit.EntityId = (int?)entry.EntityKey.EntityKeyValues[0].Value;
        //    }
        //    else
        //    {//entry is modified
        //        string oldData = GetEntryValueInString(entry, true, out modifiedProperties);
        //        if (modifiedProperties.Count > 0)
        //        {
        //            audit.OldData = oldData;
        //            audit.NewData = GetEntryValueInString(entry, false, out modifiedProperties);
        //            audit.ChangedColumns = string.Join("!", modifiedProperties.ToArray());
        //        }

        //        audit.Action = AuditActions.U.ToString();
        //        if (!entry.IsRelationship)
        //            audit.EntityId = (int?)entry.EntityKey.EntityKeyValues[0].Value;

        //    }

        //    if (entry.IsRelationship)
        //    {
        //        EntityKey rlEntityKey=(System.Data.EntityKey)(entry.State == EntityState.Added ? entry.CurrentValues[0] : entry.OriginalValues[0]);
        //        audit.TableName = rlEntityKey.EntitySetName;
        //        //if (rlEntityKey.EntityKeyValues != null)
        //            audit.EntityId = (int)rlEntityKey.EntityKeyValues[0].Value;
        //        audit.IsRelation = true;
        //    }

        //    if (audit.Action == AuditActions.U.ToString() && string.IsNullOrEmpty(audit.OldData) && string.IsNullOrEmpty(audit.NewData) && string.IsNullOrEmpty(audit.ChangedColumns))
        //    {
        //        audit = null;
        //    }
        //    return audit;
        //}

        //private string GetEntryValueInString(ObjectStateEntry entry, bool isOrginal, out List<string> modifiedProperties)
        //{
        //    modifiedProperties = new List<string>();
        //    if (!entry.IsRelationship && entry.Entity != null && entry.Entity is EntityObject)
        //    {
        //        //object target = CloneEntity((EntityObject)entry.Entity);
        //        foreach (string propName in entry.GetModifiedProperties())
        //        {
        //            object originalValue = entry.OriginalValues[propName];
        //            object currentValue = entry.CurrentValues[propName];

        //            //if (Convert.ToString(originalValue) != Convert.ToString(currentValue))
        //            if (!originalValue.Equals(currentValue))
        //            {
        //                string masterTable="";
        //                if (propName.EndsWith("_ID"))
        //                {
        //                    PropertyInfo propInfo = entry.Entity.GetType().GetProperty(propName);
        //                    masterTable = GetMasterTableName(propInfo);
        //                }
        //                modifiedProperties.Add(masterTable + "$" + propName + "$" + originalValue.ToString() + "$" + currentValue.ToString());

        //                //object setterValue = null;

        //                //if (isOrginal)
        //                //{
        //                //    //Get orginal value 
        //                //    setterValue = originalValue;
        //                //}
        //                //else
        //                //{
        //                //    //Get orginal value 
        //                //    setterValue = currentValue;
        //                //}
        //                ////Find property to update 
        //                //PropertyInfo propInfo = target.GetType().GetProperty(propName);
        //                ////update property with orgibal value 
        //                //if (setterValue == DBNull.Value)
        //                //{//
        //                //    setterValue = null;
        //                //}
        //                //propInfo.SetValue(target, setterValue, null);
        //            }
        //        }//end foreach

        //        return "";//target.SerializeToXml();
        //    }

        //    return null;
        //}

        //public EntityObject CloneEntity(EntityObject obj)
        //{
        //    DataContractSerializer dcSer = new DataContractSerializer(obj.GetType());
        //    MemoryStream memoryStream = new MemoryStream();

        //    dcSer.WriteObject(memoryStream, obj);
        //    memoryStream.Position = 0;

        //    EntityObject newObject = (EntityObject)dcSer.ReadObject(memoryStream);
        //    return newObject;
        //}

        
        //private string GetMasterTableName(PropertyInfo property)
        //{
        //    string masterTableName = "";
        //    var metaProperty = AMSObjectContextHelper.GetPropertyMetaData(property);
        //    if (metaProperty == null)
        //        return masterTableName;
        //    var atts = metaProperty.GetCustomAttributes(typeof(AdditionalMetadataAttribute), true);
        //    if (atts.Length == 0)
        //        return masterTableName;
        //    foreach (AdditionalMetadataAttribute additionalMetadataAttribute in atts)
        //    {
        //        if (additionalMetadataAttribute.Name == "MasterTable")
        //        {
        //            masterTableName = additionalMetadataAttribute.Value.ToString();
        //            break;
        //        }
        //    }
        //    return masterTableName;

        //}

    }
}
